﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using ZhonTai.Admin.Core.Attributes;
using ZhonTai.Common.Extensions;
using ZhonTai.Industry.Contracts.Core.Enums;
using ZhonTai.Industry.Contracts.Model.Dic;
using ZhonTai.Industry.Contracts.Model.Entity;
using ZhonTai.Industry.Core.Consts;
using ZhonTai.Industry.Core.Core.Common;
using ZhonTai.Industry.Domain.DeviceFormula;
using ZhonTai.Industry.Domain.FormulaDetail;

namespace ZhonTai.Industry.Core.Core.DeviceMutual
{
    /// <summary>
    /// 配方控制操作（“PLC-PC:10”） 配方控制操作（“PC-PLC:1”）
    /// </summary>
    [InjectTransient]
    public class FormulaHandle : WorkExecuteBase
    {
        private IDeviceFormulaRepository _deviceFormulaRepository;
        private IFormulaDetailRepository _formulaDetailRepository;

        public FormulaHandle(
            IDeviceFormulaRepository deviceFormulaRepository,
            IFormulaDetailRepository formulaDetailRepository)
        {
            _deviceFormulaRepository = deviceFormulaRepository;
            _formulaDetailRepository = formulaDetailRepository;
        }

        public override async Task ExecuteAsync(PushShip content)
        {
            try
            {
                if (content.Value is JsonElement element)
                {
                    switch (element.ValueKind)
                    {
                        case JsonValueKind.Number:
                            element.TryGetInt32(out int intVal);
                            if (intVal == 1)
                            {
                                var result = await UploadAsync(content);
                                if (result)
                                {
                                    await content.Example.WriteAsync(500, (short)1);
                                }
                                else
                                {
                                    await content.Example.WriteAsync(500, (short)9);
                                }
                            }
                            if (intVal == 10)
                            {
                                var result = await DownAsync(content);
                                if (result)
                                {
                                    await content.Example.WriteAsync(500, (short)10);
                                }
                                else
                                {
                                    await content.Example.WriteAsync(500, (short)9);
                                }
                            }
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                var writeResult = await content.Example.WriteAsync(500, (short)2);
                if (writeResult.IsSuccess)
                {
                    logger.Error($"工站【{content.OPCode}】配方控制错误，原因:{ex.Message},回复写入成功");
                }
            }
        }

        /// <summary>
        /// 上传配方
        /// </summary>
        /// <returns></returns>
        private async Task<bool> UploadAsync(PushShip parameter)
        {
            try
            {
                //工站ID
                long stationId = parameter.StationId;
                //MES地址
                int mesAddress = parameter.Example._mesDB.DBAddress;
                //PLC实例
                var plc = InstanceDic.PLC[parameter.StationId];
                var formulaOrderOffset = parameter.Example._mesDB.DataFields.Find(f => f.Another == OffsetConsts.FormulaOrder);
                //配方序号
                short formulaOrder = (await plc.ReadInt16Async("DB" + mesAddress + "." + formulaOrderOffset.Offset)).Content;
                if (formulaOrder == 0)
                {
                    logger.Warn($"工站【{parameter.OPCode}】配方上传失败：配方序号为0！");
                    return false;
                }
                var entity = await _deviceFormulaRepository.Select.Where(w => w.FormulaOrder == formulaOrder && w.Enabled).ToOneAsync();
                if (entity == null)
                {
                    logger.Warn($"工站【{parameter.OPCode}】配方上传失败：软件配方序号【{formulaOrder}】未启用！");
                    return false;
                }
                var formulaDetailList = await _formulaDetailRepository.Select
                    .Where(w => w.DeviceFormulaId == entity.Id && w.StationId == stationId && w.Enabled)
                    .Include(i => i.PLCOffset)
                    .OrderBy(o => o.Sort).ToListAsync();
                if (formulaDetailList.Count > 0)
                {
                    formulaDetailList.ForEach(async s =>
                    {
                        var newValue = (await plc.ReadFloatAsync("DB" + mesAddress + "." + s.PLCOffset.ByteOffset)).Content;
                        s.ParamValue = newValue.ToString();
                    });
                    await _formulaDetailRepository.UpdateAsync(formulaDetailList);
                    return true;
                }
                else
                {
                    throw new Exception("未找到对应配方参数");
                }
            }
            catch (Exception)
            {
                throw;
            }

            return false;
        }

        /// <summary>
        /// 下载配方
        /// </summary>
        /// <returns></returns>
        private async Task<bool> DownAsync(PushShip parameter)
        {
            try
            {
                //工站ID
                long stationId = parameter.StationId;
                //MES地址
                int mesAddress = parameter.Example._mesDB.DBAddress;
                //PLC实例
                var plc = InstanceDic.PLC[parameter.StationId];
                //配方序号
                var formulaOrderOffset = parameter.Example._mesDB.DataFields.Find(f => f.Another == OffsetConsts.FormulaOrder);
                short formulaOrder = (await plc.ReadInt16Async("DB" + mesAddress + "." + formulaOrderOffset.Offset)).Content;
                if (formulaOrder <= 0)
                {
                    logger.Warn($"工站【{parameter.OPCode}】配方下载失败：配方序号为0！");
                    return false;
                }
                var entity = await _deviceFormulaRepository.Select.Where(w => w.FormulaOrder == formulaOrder && w.Enabled).ToOneAsync();
                if (entity == null)
                {
                    logger.Warn($"工站【{parameter.OPCode}】配方下载失败：配方序号【{formulaOrder}】在上位机不存在！");
                    return false;
                }
                var formulaDetailList = await _formulaDetailRepository.Select
                    .Where(w => w.DeviceFormulaId == entity.Id && w.StationId == stationId && w.Enabled)
                    .Include(i => i.PLCOffset)
                    .OrderBy(o => o.Sort).ToListAsync();
                if (formulaDetailList != null)
                {
                    formulaDetailList.ForEach(async s =>
                    {
                        await plc.WriteAsync("DB" + mesAddress + "." + s.PLCOffset.ByteOffset, Convert.ToSingle(s.ParamValue));
                    });
                    return true;
                }
            }
            catch (Exception)
            {
                throw;
            }
            return false;
        }
    }
}